{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "36c9bb56",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:34:07.207495Z",
     "start_time": "2022-04-27T06:34:02.288722Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import datetime\n",
    "\n",
    "import paddle\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from collections import deque\n",
    "\n",
    "from tqdm import tqdm\n",
    "from sklearn.metrics import mean_absolute_percentage_error\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from sklearn.ensemble import RandomForestRegressor\n",
    "from paddle import nn\n",
    "from paddle.io import Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "696c7c24",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:34:25.789660Z",
     "start_time": "2022-04-27T06:34:25.766442Z"
    },
    "code_folding": [
     91
    ]
   },
   "outputs": [],
   "source": [
    "# utility functions\n",
    "\n",
    "def handle_timestamp(df):\n",
    "    \"\"\"增加时间戳\"\"\"\n",
    "    timestamp = df['日期'] + ' ' + df['时间']\n",
    "    timestamp = timestamp.map(lambda i: i.replace('24:00', '00:00'))\n",
    "    timestamp = pd.to_datetime(timestamp)\n",
    "    index = timestamp[timestamp.map(lambda i: i.hour == 0 and i.minute == 0)].index\n",
    "    timestamp[index] = timestamp[index].map(lambda i: i + datetime.timedelta(1))\n",
    "    df['时间戳'] = timestamp\n",
    "    return df\n",
    "\n",
    "\n",
    "def add_fea(df):\n",
    "    \"\"\"\n",
    "    根据时间戳来增加三个新特征。\n",
    "    \n",
    "    当前时刻是否为出力高峰（出力高峰时间段：10:00~15:00），0：否，1：是\n",
    "    当天是星期几，0：周一，1：周二，...，6：周日\n",
    "    当天是否为周末，0：否，1：是\n",
    "    \"\"\"\n",
    "    is_peak = []\n",
    "    weekday = []\n",
    "    is_weekend = []\n",
    "    timestap = pd.to_datetime(df['时间戳'])\n",
    "    for t in timestap:\n",
    "        if 10 <= t.hour <= 15:\n",
    "            is_peak.append(1)\n",
    "        else:\n",
    "            is_peak.append(0)\n",
    "        \n",
    "        wd = t.weekday()\n",
    "        weekday.append(wd)\n",
    "        if wd in [5, 6]:\n",
    "            is_weekend.append(1)\n",
    "        else:\n",
    "            is_weekend.append(0)\n",
    "    df['is_peak'] = is_peak\n",
    "    df['weekday'] = weekday\n",
    "    df['is_weekend'] = is_weekend\n",
    "    return df\n",
    "\n",
    "\n",
    "def scale_fea(df):\n",
    "    \"\"\"对特征进行最大最小值归一化处理\"\"\"\n",
    "    df_scaled = df.copy()\n",
    "    scaler = MinMaxScaler()\n",
    "    price_scaler = MinMaxScaler()\n",
    "    df_scaled[['省调负荷-日前(MW)', '火电竞价空间-日前(MW)', '新能源负荷-日前(MW)',]] = \\\n",
    "        scaler.fit_transform(df[['省调负荷-日前(MW)', '火电竞价空间-日前(MW)', '新能源负荷-日前(MW)',]])\n",
    "    df_scaled['统一出清价格-日前(元/MWh)'] = price_scaler.fit_transform(df[['统一出清价格-日前(元/MWh)']])\n",
    "    return df_scaled, price_scaler\n",
    "\n",
    "\n",
    "def create_sequence(df, window: int = 192):\n",
    "    \"\"\"\n",
    "    为了能够输入LSTM模型，将数据处理成序列的形式。\n",
    "\n",
    "    默认选用2天（共192个数据点）的样本作为输入序列并预测下一个点的价格，样本的特征包括：省调负荷，\n",
    "    火电竞价空间，新能源负荷，统一出清价格，是否出力高峰，周几、是否周末。\n",
    "\n",
    "    假设输入的df一共有N行，那么处理后的数据的维度为：[N-window, window, 7]\n",
    "    \"\"\"\n",
    "    N = df.shape[0]\n",
    "    ret = np.empty(shape=(N - window, window, 6))\n",
    "    y = np.empty(N - window)\n",
    "    for i in range(N - window):\n",
    "        end = i + window\n",
    "#         arr = df[['省调负荷-日前(MW)', '火电竞价空间-日前(MW)', '新能源负荷-日前(MW)',\n",
    "#                   '统一出清价格-日前(元/MWh)', 'is_peak', 'weekday', 'is_weekend']].iloc[i: end].values\n",
    "        arr = df[['省调负荷-日前(MW)', '火电竞价空间-日前(MW)',\n",
    "                  'is_peak', 'weekday', 'is_weekend', '统一出清价格-日前(元/MWh)']].iloc[i: end].values\n",
    "        ret[i] = arr\n",
    "        y[i] = df['统一出清价格-日前(元/MWh)'].iloc[i + window]\n",
    "    return ret, y\n",
    "\n",
    "\n",
    "def filtered_mape(y_true: list, y_pred: list):\n",
    "    \"\"\"为了使mape的值更加合理，过滤掉其中的0值\"\"\"\n",
    "    y_true_filtered, y_pred_filtered = [], []\n",
    "    for i in range(len(y_true)):\n",
    "        if y_true[i] != 0:\n",
    "            y_true_filtered.append(y_true[i])\n",
    "            y_pred_filtered.append(y_pred[i])\n",
    "#         else:\n",
    "#             y_true_filtered.append(y_true[i] + 0.01)\n",
    "#             y_pred_filtered.append(y_pred[i] + 0.01)\n",
    "            \n",
    "    return mean_absolute_percentage_error(y_true_filtered, y_pred_filtered)\n",
    "\n",
    "\n",
    "def plot_curve(true_value_list: list, pred_value_list: list, timestamp,\n",
    "               start_idx: int = 1, interval: int = 1):\n",
    "    \"\"\"\n",
    "    绘制真实值与预测值的对比曲线。为了能够看得清楚，渲染的点的数量为[96, 3*96]，且\n",
    "    每次增加96个点。\n",
    "    \"\"\"\n",
    "    assert len(true_value_list) == len(pred_value_list), '数据列表长度须一致！'\n",
    "    \n",
    "    assert interval in [1, 2, 3]\n",
    "    interval_num = interval * 96\n",
    "    \n",
    "    start = start_idx * interval_num\n",
    "    end = (start_idx + 1) * interval_num\n",
    "    \n",
    "    x = timestamp[start: end]\n",
    "    y_true = true_value_list[start: end]\n",
    "    y_pred = pred_value_list[start: end]\n",
    "    \n",
    "    fig, ax = plt.subplots()\n",
    "    fig.autofmt_xdate()\n",
    "    \n",
    "    ax.plot(x, y_true, color='r', label='true value')\n",
    "    ax.plot(x, y_pred, color='g', label='predict value')\n",
    "    \n",
    "    plt.xticks(range(0, interval_num, interval*10))\n",
    "    ax.legend()\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "06980530",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:34:27.620396Z",
     "start_time": "2022-04-27T06:34:27.615359Z"
    }
   },
   "outputs": [],
   "source": [
    "data_home_path = ''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "777d6833",
   "metadata": {
    "code_folding": [
     0
    ]
   },
   "outputs": [],
   "source": [
    "#\n",
    "# 已经处理完成，直接执行下个cell的代码进行导入即可\n",
    "#\n",
    "\n",
    "# 1. 原始数据读入\n",
    "df_省调负荷_1 = pd.read_excel(data_home_path + '省调负荷数据（2021-04-01至2021-12-31）.xlsx')\n",
    "df_省调负荷_2 = pd.read_excel(data_home_path + '省调负荷数据（2022-01-01至2022-04-20）.xlsx')\n",
    "\n",
    "df_竞价_1 = pd.read_excel(data_home_path + '火电竞价空间数据（2021-04-01至2021-12-31）.xlsx')\n",
    "df_竞价_2 = pd.read_excel(data_home_path + '火电竞价空间数据（2022-01-01至2022-04-20）.xlsx')\n",
    "\n",
    "df_新能源负荷_1 = pd.read_excel(data_home_path + '新能源负荷数据（2021-04-01至2021-12-31）.xlsx')\n",
    "df_新能源负荷_2 = pd.read_excel(data_home_path + '新能源负荷数据（2022-01-01至2022-04-20）.xlsx')\n",
    "\n",
    "df_price = pd.read_excel(data_home_path + '统一出清价格数据（2021-04-01至2022-04-20）.xlsx')\n",
    "\n",
    "\n",
    "# 2. 数据拼接\n",
    "df_省调负荷 = df_省调负荷_1.append(df_省调负荷_2).reset_index()\n",
    "df_竞价 = df_竞价_1.append(df_竞价_2).reset_index()\n",
    "df_新能源负荷 = df_新能源负荷_1.append(df_新能源负荷_2).reset_index()\n",
    "\n",
    "\n",
    "# 3. 处理时间戳\n",
    "df_省调负荷 = handle_timestamp(df_省调负荷)\n",
    "df_竞价 = handle_timestamp(df_竞价)\n",
    "df_新能源负荷 = handle_timestamp(df_新能源负荷)\n",
    "df_price = handle_timestamp(df_price)\n",
    "\n",
    "\n",
    "# 4. 特征过滤\n",
    "df_省调负荷 = df_省调负荷[['省调负荷-日前(MW)', '省调负荷-实时(MW)', '时间戳']]\n",
    "df_竞价 = df_竞价[['火电竞价空间-日前(MW)', '火电竞价空间-实时(MW)', '时间戳']]\n",
    "df_新能源负荷 = df_新能源负荷[['新能源负荷-日前(MW)', '新能源负荷-实时(MW)', '时间戳']]\n",
    "df_price = df_price[['统一出清价格-日前(元/MWh)', '统一出清价格-日前预测', '统一出清价格-实时(元/MWh)', '时间戳']]\n",
    "\n",
    "\n",
    "# 5. 全部数据拼接\n",
    "all_df = df_省调负荷.merge(df_竞价).merge(df_新能源负荷).merge(df_price)\n",
    "\n",
    "\n",
    "# 6. 数据写出\n",
    "all_df.to_csv(data_home_path + 'all_df.csv', index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ef5ad35d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:34:56.970576Z",
     "start_time": "2022-04-27T06:34:30.858348Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/sunjiawei/opt/anaconda3/envs/code/lib/python3.7/site-packages/paddle/fluid/data_feeder.py:51: DeprecationWarning: `np.bool` is a deprecated alias for the builtin `bool`. To silence this warning, use `bool` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.bool_` here.\n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  np.bool, np.float16, np.uint16, np.float32, np.float64, np.int8,\n"
     ]
    }
   ],
   "source": [
    "# total cost≈25s\n",
    "\n",
    "# 导入\n",
    "all_df = pd.read_csv(data_home_path + 'all_df.csv')\n",
    "# 增加特征\n",
    "all_df = add_fea(all_df)\n",
    "# 归一化\n",
    "all_df_scaled, price_scaler = scale_fea(all_df)\n",
    "# 序列化\n",
    "ret, y = create_sequence(all_df_scaled)\n",
    "# 训练集测试集划分\n",
    "train_size = int(y.shape[0] * 0.8)\n",
    "test_size = y.shape[0] - train_size\n",
    "train_X = ret[:train_size]\n",
    "train_y = y[:train_size]\n",
    "test_X = ret[-test_size:]\n",
    "test_y = y[-test_size:]\n",
    "\n",
    "# tensor化\n",
    "train_X_tensor = paddle.to_tensor(train_X, dtype=np.float32)\n",
    "train_y_tensor = paddle.to_tensor(train_y, dtype=np.float32)\n",
    "test_X_tensor = paddle.to_tensor(test_X, dtype=np.float32)\n",
    "test_y_tensor = paddle.to_tensor(test_y, dtype=np.float32)\n",
    "\n",
    "# 序列化后的数据的时间戳\n",
    "timestamp_seq = all_df['时间戳'].iloc[192:]\n",
    "test_timestamp = timestamp_seq[-test_size:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "166919c3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:34:56.981534Z",
     "start_time": "2022-04-27T06:34:56.973417Z"
    }
   },
   "outputs": [],
   "source": [
    "# 工具类，用于定义模型结构和训练/预测\n",
    "class MyLSTM(nn.LSTM):\n",
    "    def __init__(self, *args, **kwargs):\n",
    "        super().__init__(*args, **kwargs)\n",
    "    \n",
    "    def forward(self, inputs):\n",
    "        output, _ = super().forward(inputs)\n",
    "        return output[:, -1, :]\n",
    "\n",
    "\n",
    "class MyDataset(Dataset):\n",
    "    def __init__(self, dataset_type, sub_tensor=None):\n",
    "        self.dataset_type = dataset_type\n",
    "        self.sub_tensor = sub_tensor\n",
    "    \n",
    "    def __getitem__(self, idx):\n",
    "        if self.dataset_type == 'train':\n",
    "            return train_X_tensor[idx], train_y_tensor[idx]\n",
    "        if self.dataset_type == 'test':\n",
    "            return self.sub_tensor\n",
    "\n",
    "    def __len__(self):\n",
    "        if self.dataset_type == 'train':\n",
    "            return len(train_y_tensor)\n",
    "        if self.dataset_type == 'test':\n",
    "            return 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "08510cd5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:37:33.970570Z",
     "start_time": "2022-04-27T06:34:56.983529Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The loss value printed in the log is the current step, and the metric is the average value of previous steps.\n",
      "Epoch 1/5\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/sunjiawei/opt/anaconda3/envs/code/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:77: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working\n",
      "  return (isinstance(seq, collections.Sequence) and\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step  10/920 - loss: 0.0389 - 39ms/step\n",
      "step  20/920 - loss: 0.0510 - 35ms/step\n",
      "step  30/920 - loss: 0.0437 - 35ms/step\n",
      "step  40/920 - loss: 0.0394 - 35ms/step\n",
      "step  50/920 - loss: 0.0228 - 34ms/step\n",
      "step  60/920 - loss: 0.0394 - 34ms/step\n",
      "step  70/920 - loss: 0.0219 - 34ms/step\n",
      "step  80/920 - loss: 0.0400 - 35ms/step\n",
      "step  90/920 - loss: 0.0429 - 35ms/step\n",
      "step 100/920 - loss: 0.0317 - 35ms/step\n",
      "step 110/920 - loss: 0.0156 - 34ms/step\n",
      "step 120/920 - loss: 0.0309 - 34ms/step\n",
      "step 130/920 - loss: 0.0114 - 34ms/step\n",
      "step 140/920 - loss: 0.0176 - 34ms/step\n",
      "step 150/920 - loss: 0.0193 - 34ms/step\n",
      "step 160/920 - loss: 0.0210 - 34ms/step\n",
      "step 170/920 - loss: 0.0179 - 34ms/step\n",
      "step 180/920 - loss: 0.0244 - 34ms/step\n",
      "step 190/920 - loss: 0.0098 - 34ms/step\n",
      "step 200/920 - loss: 0.0191 - 33ms/step\n",
      "step 210/920 - loss: 0.0129 - 33ms/step\n",
      "step 220/920 - loss: 0.0210 - 33ms/step\n",
      "step 230/920 - loss: 0.0074 - 33ms/step\n",
      "step 240/920 - loss: 0.0123 - 33ms/step\n",
      "step 250/920 - loss: 0.0097 - 33ms/step\n",
      "step 260/920 - loss: 0.0265 - 33ms/step\n",
      "step 270/920 - loss: 0.0075 - 33ms/step\n",
      "step 280/920 - loss: 0.0100 - 33ms/step\n",
      "step 290/920 - loss: 0.0086 - 33ms/step\n",
      "step 300/920 - loss: 0.0174 - 33ms/step\n",
      "step 310/920 - loss: 0.0104 - 33ms/step\n",
      "step 320/920 - loss: 0.0201 - 33ms/step\n",
      "step 330/920 - loss: 0.0160 - 33ms/step\n",
      "step 340/920 - loss: 0.0162 - 33ms/step\n",
      "step 350/920 - loss: 0.0115 - 33ms/step\n",
      "step 360/920 - loss: 0.0074 - 33ms/step\n",
      "step 370/920 - loss: 0.0057 - 33ms/step\n",
      "step 380/920 - loss: 0.0195 - 33ms/step\n",
      "step 390/920 - loss: 0.0220 - 33ms/step\n",
      "step 400/920 - loss: 0.0167 - 33ms/step\n",
      "step 410/920 - loss: 0.0086 - 33ms/step\n",
      "step 420/920 - loss: 0.0117 - 33ms/step\n",
      "step 430/920 - loss: 0.0291 - 33ms/step\n",
      "step 440/920 - loss: 0.0121 - 33ms/step\n",
      "step 450/920 - loss: 0.0094 - 33ms/step\n",
      "step 460/920 - loss: 0.0099 - 32ms/step\n",
      "step 470/920 - loss: 0.0075 - 33ms/step\n",
      "step 480/920 - loss: 0.0062 - 32ms/step\n",
      "step 490/920 - loss: 0.0112 - 32ms/step\n",
      "step 500/920 - loss: 0.0121 - 32ms/step\n",
      "step 510/920 - loss: 0.0099 - 32ms/step\n",
      "step 520/920 - loss: 0.0215 - 32ms/step\n",
      "step 530/920 - loss: 0.0090 - 32ms/step\n",
      "step 540/920 - loss: 0.0147 - 32ms/step\n",
      "step 550/920 - loss: 0.0102 - 32ms/step\n",
      "step 560/920 - loss: 0.0047 - 32ms/step\n",
      "step 570/920 - loss: 0.0046 - 33ms/step\n",
      "step 580/920 - loss: 0.0079 - 33ms/step\n",
      "step 590/920 - loss: 0.0058 - 33ms/step\n",
      "step 600/920 - loss: 0.0086 - 33ms/step\n",
      "step 610/920 - loss: 0.0058 - 33ms/step\n",
      "step 620/920 - loss: 0.0142 - 33ms/step\n",
      "step 630/920 - loss: 0.0054 - 33ms/step\n",
      "step 640/920 - loss: 0.0049 - 33ms/step\n",
      "step 650/920 - loss: 0.0092 - 33ms/step\n",
      "step 660/920 - loss: 0.0179 - 33ms/step\n",
      "step 670/920 - loss: 0.0053 - 33ms/step\n",
      "step 680/920 - loss: 0.0131 - 33ms/step\n",
      "step 690/920 - loss: 0.0056 - 33ms/step\n",
      "step 700/920 - loss: 0.0093 - 33ms/step\n",
      "step 710/920 - loss: 0.0147 - 33ms/step\n",
      "step 720/920 - loss: 0.0049 - 33ms/step\n",
      "step 730/920 - loss: 0.0056 - 33ms/step\n",
      "step 740/920 - loss: 0.0106 - 33ms/step\n",
      "step 750/920 - loss: 0.0079 - 33ms/step\n",
      "step 760/920 - loss: 0.0075 - 33ms/step\n",
      "step 770/920 - loss: 0.0056 - 33ms/step\n",
      "step 780/920 - loss: 0.0143 - 33ms/step\n",
      "step 790/920 - loss: 0.0030 - 33ms/step\n",
      "step 800/920 - loss: 0.0098 - 33ms/step\n",
      "step 810/920 - loss: 0.0043 - 33ms/step\n",
      "step 820/920 - loss: 0.0062 - 33ms/step\n",
      "step 830/920 - loss: 0.0021 - 33ms/step\n",
      "step 840/920 - loss: 0.0131 - 33ms/step\n",
      "step 850/920 - loss: 0.0075 - 33ms/step\n",
      "step 860/920 - loss: 0.0051 - 33ms/step\n",
      "step 870/920 - loss: 0.0050 - 33ms/step\n",
      "step 880/920 - loss: 0.0080 - 33ms/step\n",
      "step 890/920 - loss: 0.0062 - 33ms/step\n",
      "step 900/920 - loss: 0.0039 - 33ms/step\n",
      "step 910/920 - loss: 0.0085 - 33ms/step\n",
      "step 920/920 - loss: 0.0012 - 33ms/step\n",
      "Epoch 2/5\n",
      "step  10/920 - loss: 0.0035 - 33ms/step\n",
      "step  20/920 - loss: 0.0029 - 33ms/step\n",
      "step  30/920 - loss: 0.0052 - 33ms/step\n",
      "step  40/920 - loss: 0.0060 - 33ms/step\n",
      "step  50/920 - loss: 0.0065 - 33ms/step\n",
      "step  60/920 - loss: 0.0057 - 32ms/step\n",
      "step  70/920 - loss: 0.0100 - 32ms/step\n",
      "step  80/920 - loss: 0.0101 - 32ms/step\n",
      "step  90/920 - loss: 0.0033 - 32ms/step\n",
      "step 100/920 - loss: 0.0058 - 32ms/step\n",
      "step 110/920 - loss: 0.0094 - 32ms/step\n",
      "step 120/920 - loss: 0.0037 - 31ms/step\n",
      "step 130/920 - loss: 0.0045 - 31ms/step\n",
      "step 140/920 - loss: 0.0035 - 31ms/step\n",
      "step 150/920 - loss: 0.0022 - 31ms/step\n",
      "step 160/920 - loss: 0.0092 - 31ms/step\n",
      "step 170/920 - loss: 0.0044 - 31ms/step\n",
      "step 180/920 - loss: 0.0013 - 31ms/step\n",
      "step 190/920 - loss: 0.0060 - 31ms/step\n",
      "step 200/920 - loss: 0.0055 - 31ms/step\n",
      "step 210/920 - loss: 0.0022 - 31ms/step\n",
      "step 220/920 - loss: 0.0046 - 31ms/step\n",
      "step 230/920 - loss: 0.0174 - 31ms/step\n",
      "step 240/920 - loss: 0.0041 - 31ms/step\n",
      "step 250/920 - loss: 0.0033 - 31ms/step\n",
      "step 260/920 - loss: 0.0018 - 31ms/step\n",
      "step 270/920 - loss: 0.0021 - 31ms/step\n",
      "step 280/920 - loss: 0.0039 - 31ms/step\n",
      "step 290/920 - loss: 0.0028 - 31ms/step\n",
      "step 300/920 - loss: 0.0032 - 31ms/step\n",
      "step 310/920 - loss: 0.0027 - 31ms/step\n",
      "step 320/920 - loss: 0.0043 - 31ms/step\n",
      "step 330/920 - loss: 0.0032 - 31ms/step\n",
      "step 340/920 - loss: 0.0017 - 30ms/step\n",
      "step 350/920 - loss: 0.0018 - 30ms/step\n",
      "step 360/920 - loss: 0.0036 - 30ms/step\n",
      "step 370/920 - loss: 0.0020 - 30ms/step\n",
      "step 380/920 - loss: 0.0061 - 30ms/step\n",
      "step 390/920 - loss: 0.0029 - 30ms/step\n",
      "step 400/920 - loss: 0.0070 - 30ms/step\n",
      "step 410/920 - loss: 0.0105 - 30ms/step\n",
      "step 420/920 - loss: 0.0050 - 30ms/step\n",
      "step 430/920 - loss: 0.0036 - 30ms/step\n",
      "step 440/920 - loss: 0.0092 - 30ms/step\n",
      "step 450/920 - loss: 0.0141 - 30ms/step\n",
      "step 460/920 - loss: 0.0055 - 30ms/step\n",
      "step 470/920 - loss: 0.0090 - 30ms/step\n",
      "step 480/920 - loss: 0.0025 - 30ms/step\n",
      "step 490/920 - loss: 0.0035 - 30ms/step\n",
      "step 500/920 - loss: 0.0029 - 30ms/step\n",
      "step 510/920 - loss: 0.0073 - 30ms/step\n",
      "step 520/920 - loss: 0.0138 - 30ms/step\n",
      "step 530/920 - loss: 0.0028 - 30ms/step\n",
      "step 540/920 - loss: 0.0020 - 30ms/step\n",
      "step 550/920 - loss: 0.0043 - 30ms/step\n",
      "step 560/920 - loss: 0.0077 - 30ms/step\n",
      "step 570/920 - loss: 0.0022 - 30ms/step\n",
      "step 580/920 - loss: 0.0032 - 30ms/step\n",
      "step 590/920 - loss: 0.0014 - 30ms/step\n",
      "step 600/920 - loss: 0.0032 - 30ms/step\n",
      "step 610/920 - loss: 0.0022 - 30ms/step\n",
      "step 620/920 - loss: 0.0018 - 30ms/step\n",
      "step 630/920 - loss: 0.0067 - 30ms/step\n",
      "step 640/920 - loss: 0.0042 - 30ms/step\n",
      "step 650/920 - loss: 0.0015 - 30ms/step\n",
      "step 660/920 - loss: 0.0023 - 30ms/step\n",
      "step 670/920 - loss: 0.0014 - 30ms/step\n",
      "step 680/920 - loss: 0.0035 - 30ms/step\n",
      "step 690/920 - loss: 0.0042 - 30ms/step\n",
      "step 700/920 - loss: 0.0056 - 30ms/step\n",
      "step 710/920 - loss: 0.0019 - 30ms/step\n",
      "step 720/920 - loss: 0.0039 - 30ms/step\n",
      "step 730/920 - loss: 0.0027 - 30ms/step\n",
      "step 740/920 - loss: 0.0060 - 30ms/step\n",
      "step 750/920 - loss: 0.0040 - 30ms/step\n",
      "step 760/920 - loss: 0.0015 - 30ms/step\n",
      "step 770/920 - loss: 0.0023 - 30ms/step\n",
      "step 780/920 - loss: 0.0018 - 30ms/step\n",
      "step 790/920 - loss: 0.0038 - 30ms/step\n",
      "step 800/920 - loss: 0.0033 - 30ms/step\n",
      "step 810/920 - loss: 0.0025 - 30ms/step\n",
      "step 820/920 - loss: 0.0080 - 30ms/step\n",
      "step 830/920 - loss: 0.0016 - 30ms/step\n",
      "step 840/920 - loss: 0.0028 - 30ms/step\n",
      "step 850/920 - loss: 0.0016 - 30ms/step\n",
      "step 860/920 - loss: 0.0025 - 30ms/step\n",
      "step 870/920 - loss: 0.0046 - 30ms/step\n",
      "step 880/920 - loss: 0.0027 - 30ms/step\n",
      "step 890/920 - loss: 0.0080 - 30ms/step\n",
      "step 900/920 - loss: 0.0036 - 30ms/step\n",
      "step 910/920 - loss: 0.0053 - 30ms/step\n",
      "step 920/920 - loss: 2.5612e-04 - 30ms/step\n",
      "Epoch 3/5\n",
      "step  10/920 - loss: 0.0014 - 31ms/step\n",
      "step  20/920 - loss: 0.0050 - 31ms/step\n",
      "step  30/920 - loss: 0.0022 - 31ms/step\n",
      "step  40/920 - loss: 0.0026 - 31ms/step\n",
      "step  50/920 - loss: 0.0113 - 31ms/step\n",
      "step  60/920 - loss: 0.0025 - 31ms/step\n",
      "step  70/920 - loss: 0.0013 - 31ms/step\n",
      "step  80/920 - loss: 0.0022 - 31ms/step\n",
      "step  90/920 - loss: 0.0017 - 31ms/step\n",
      "step 100/920 - loss: 0.0018 - 31ms/step\n",
      "step 110/920 - loss: 0.0021 - 31ms/step\n",
      "step 120/920 - loss: 0.0028 - 31ms/step\n",
      "step 130/920 - loss: 0.0034 - 31ms/step\n",
      "step 140/920 - loss: 0.0035 - 31ms/step\n",
      "step 150/920 - loss: 0.0011 - 31ms/step\n",
      "step 160/920 - loss: 0.0028 - 31ms/step\n",
      "step 170/920 - loss: 0.0015 - 31ms/step\n",
      "step 180/920 - loss: 0.0020 - 31ms/step\n",
      "step 190/920 - loss: 0.0045 - 31ms/step\n",
      "step 200/920 - loss: 0.0025 - 31ms/step\n",
      "step 210/920 - loss: 0.0030 - 31ms/step\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step 220/920 - loss: 0.0011 - 31ms/step\n",
      "step 230/920 - loss: 0.0019 - 31ms/step\n",
      "step 240/920 - loss: 0.0028 - 31ms/step\n",
      "step 250/920 - loss: 0.0018 - 31ms/step\n",
      "step 260/920 - loss: 0.0023 - 31ms/step\n",
      "step 270/920 - loss: 0.0028 - 31ms/step\n",
      "step 280/920 - loss: 0.0018 - 31ms/step\n",
      "step 290/920 - loss: 8.8834e-04 - 31ms/step\n",
      "step 300/920 - loss: 0.0027 - 31ms/step\n",
      "step 310/920 - loss: 0.0016 - 31ms/step\n",
      "step 320/920 - loss: 0.0020 - 31ms/step\n",
      "step 330/920 - loss: 0.0077 - 32ms/step\n",
      "step 340/920 - loss: 0.0039 - 32ms/step\n",
      "step 350/920 - loss: 0.0020 - 32ms/step\n",
      "step 360/920 - loss: 0.0020 - 32ms/step\n",
      "step 370/920 - loss: 0.0020 - 32ms/step\n",
      "step 380/920 - loss: 0.0017 - 32ms/step\n",
      "step 390/920 - loss: 0.0015 - 32ms/step\n",
      "step 400/920 - loss: 0.0041 - 32ms/step\n",
      "step 410/920 - loss: 0.0017 - 32ms/step\n",
      "step 420/920 - loss: 0.0018 - 32ms/step\n",
      "step 430/920 - loss: 0.0019 - 32ms/step\n",
      "step 440/920 - loss: 0.0020 - 32ms/step\n",
      "step 450/920 - loss: 9.3409e-04 - 32ms/step\n",
      "step 460/920 - loss: 7.6365e-04 - 32ms/step\n",
      "step 470/920 - loss: 0.0012 - 32ms/step\n",
      "step 480/920 - loss: 0.0028 - 32ms/step\n",
      "step 490/920 - loss: 0.0053 - 32ms/step\n",
      "step 500/920 - loss: 9.8983e-04 - 32ms/step\n",
      "step 510/920 - loss: 0.0018 - 32ms/step\n",
      "step 520/920 - loss: 0.0026 - 32ms/step\n",
      "step 530/920 - loss: 0.0015 - 32ms/step\n",
      "step 540/920 - loss: 8.7372e-04 - 32ms/step\n",
      "step 550/920 - loss: 0.0015 - 32ms/step\n",
      "step 560/920 - loss: 0.0030 - 32ms/step\n",
      "step 570/920 - loss: 0.0014 - 32ms/step\n",
      "step 580/920 - loss: 0.0018 - 32ms/step\n",
      "step 590/920 - loss: 0.0049 - 32ms/step\n",
      "step 600/920 - loss: 0.0019 - 32ms/step\n",
      "step 610/920 - loss: 0.0013 - 32ms/step\n",
      "step 620/920 - loss: 0.0019 - 32ms/step\n",
      "step 630/920 - loss: 0.0025 - 32ms/step\n",
      "step 640/920 - loss: 0.0011 - 32ms/step\n",
      "step 650/920 - loss: 0.0023 - 32ms/step\n",
      "step 660/920 - loss: 0.0024 - 32ms/step\n",
      "step 670/920 - loss: 0.0017 - 32ms/step\n",
      "step 680/920 - loss: 0.0021 - 32ms/step\n",
      "step 690/920 - loss: 0.0018 - 32ms/step\n",
      "step 700/920 - loss: 0.0022 - 32ms/step\n",
      "step 710/920 - loss: 0.0011 - 32ms/step\n",
      "step 720/920 - loss: 4.8672e-04 - 32ms/step\n",
      "step 730/920 - loss: 0.0013 - 33ms/step\n",
      "step 740/920 - loss: 0.0092 - 33ms/step\n",
      "step 750/920 - loss: 0.0102 - 33ms/step\n",
      "step 760/920 - loss: 9.1528e-04 - 33ms/step\n",
      "step 770/920 - loss: 0.0010 - 33ms/step\n",
      "step 780/920 - loss: 0.0055 - 33ms/step\n",
      "step 790/920 - loss: 0.0032 - 33ms/step\n",
      "step 800/920 - loss: 0.0013 - 33ms/step\n",
      "step 810/920 - loss: 0.0018 - 33ms/step\n",
      "step 820/920 - loss: 0.0013 - 33ms/step\n",
      "step 830/920 - loss: 0.0015 - 33ms/step\n",
      "step 840/920 - loss: 0.0029 - 33ms/step\n",
      "step 850/920 - loss: 0.0019 - 33ms/step\n",
      "step 860/920 - loss: 0.0015 - 33ms/step\n",
      "step 870/920 - loss: 0.0022 - 33ms/step\n",
      "step 880/920 - loss: 0.0026 - 33ms/step\n",
      "step 890/920 - loss: 0.0013 - 33ms/step\n",
      "step 900/920 - loss: 0.0013 - 33ms/step\n",
      "step 910/920 - loss: 0.0014 - 33ms/step\n",
      "step 920/920 - loss: 0.0014 - 33ms/step\n",
      "Epoch 4/5\n",
      "step  10/920 - loss: 0.0021 - 34ms/step\n",
      "step  20/920 - loss: 9.4561e-04 - 33ms/step\n",
      "step  30/920 - loss: 6.1469e-04 - 35ms/step\n",
      "step  40/920 - loss: 0.0032 - 35ms/step\n",
      "step  50/920 - loss: 0.0011 - 35ms/step\n",
      "step  60/920 - loss: 0.0021 - 35ms/step\n",
      "step  70/920 - loss: 0.0025 - 35ms/step\n",
      "step  80/920 - loss: 0.0014 - 35ms/step\n",
      "step  90/920 - loss: 0.0010 - 35ms/step\n",
      "step 100/920 - loss: 0.0011 - 35ms/step\n",
      "step 110/920 - loss: 0.0012 - 35ms/step\n",
      "step 120/920 - loss: 0.0018 - 35ms/step\n",
      "step 130/920 - loss: 0.0018 - 35ms/step\n",
      "step 140/920 - loss: 0.0025 - 35ms/step\n",
      "step 150/920 - loss: 0.0115 - 35ms/step\n",
      "step 160/920 - loss: 0.0015 - 35ms/step\n",
      "step 170/920 - loss: 9.5451e-04 - 36ms/step\n",
      "step 180/920 - loss: 0.0015 - 36ms/step\n",
      "step 190/920 - loss: 0.0013 - 36ms/step\n",
      "step 200/920 - loss: 0.0053 - 36ms/step\n",
      "step 210/920 - loss: 0.0030 - 36ms/step\n",
      "step 220/920 - loss: 0.0018 - 36ms/step\n",
      "step 230/920 - loss: 0.0024 - 36ms/step\n",
      "step 240/920 - loss: 0.0022 - 36ms/step\n",
      "step 250/920 - loss: 9.5518e-04 - 36ms/step\n",
      "step 260/920 - loss: 0.0010 - 36ms/step\n",
      "step 270/920 - loss: 0.0030 - 36ms/step\n",
      "step 280/920 - loss: 0.0023 - 36ms/step\n",
      "step 290/920 - loss: 0.0037 - 36ms/step\n",
      "step 300/920 - loss: 0.0029 - 36ms/step\n",
      "step 310/920 - loss: 0.0043 - 36ms/step\n",
      "step 320/920 - loss: 0.0021 - 36ms/step\n",
      "step 330/920 - loss: 0.0028 - 37ms/step\n",
      "step 340/920 - loss: 0.0014 - 37ms/step\n",
      "step 350/920 - loss: 8.6607e-04 - 37ms/step\n",
      "step 360/920 - loss: 0.0027 - 37ms/step\n",
      "step 370/920 - loss: 0.0010 - 37ms/step\n",
      "step 380/920 - loss: 0.0022 - 37ms/step\n",
      "step 390/920 - loss: 0.0022 - 37ms/step\n",
      "step 400/920 - loss: 0.0029 - 37ms/step\n",
      "step 410/920 - loss: 0.0013 - 37ms/step\n",
      "step 420/920 - loss: 0.0023 - 37ms/step\n",
      "step 430/920 - loss: 7.0509e-04 - 37ms/step\n",
      "step 440/920 - loss: 7.9199e-04 - 37ms/step\n",
      "step 450/920 - loss: 0.0029 - 37ms/step\n",
      "step 460/920 - loss: 0.0016 - 37ms/step\n",
      "step 470/920 - loss: 7.6965e-04 - 37ms/step\n",
      "step 480/920 - loss: 0.0023 - 37ms/step\n",
      "step 490/920 - loss: 0.0025 - 37ms/step\n",
      "step 500/920 - loss: 8.0148e-04 - 37ms/step\n",
      "step 510/920 - loss: 0.0078 - 37ms/step\n",
      "step 520/920 - loss: 0.0024 - 37ms/step\n",
      "step 530/920 - loss: 0.0016 - 37ms/step\n",
      "step 540/920 - loss: 0.0011 - 37ms/step\n",
      "step 550/920 - loss: 0.0021 - 38ms/step\n",
      "step 560/920 - loss: 0.0037 - 38ms/step\n",
      "step 570/920 - loss: 0.0015 - 38ms/step\n",
      "step 580/920 - loss: 7.2155e-04 - 38ms/step\n",
      "step 590/920 - loss: 0.0012 - 38ms/step\n",
      "step 600/920 - loss: 7.9537e-04 - 38ms/step\n",
      "step 610/920 - loss: 0.0011 - 38ms/step\n",
      "step 620/920 - loss: 0.0035 - 38ms/step\n",
      "step 630/920 - loss: 0.0022 - 38ms/step\n",
      "step 640/920 - loss: 7.8077e-04 - 38ms/step\n",
      "step 650/920 - loss: 0.0025 - 38ms/step\n",
      "step 660/920 - loss: 3.9801e-04 - 38ms/step\n",
      "step 670/920 - loss: 0.0029 - 38ms/step\n",
      "step 680/920 - loss: 0.0028 - 38ms/step\n",
      "step 690/920 - loss: 9.1295e-04 - 38ms/step\n",
      "step 700/920 - loss: 0.0018 - 38ms/step\n",
      "step 710/920 - loss: 0.0016 - 38ms/step\n",
      "step 720/920 - loss: 8.3288e-04 - 38ms/step\n",
      "step 730/920 - loss: 0.0023 - 38ms/step\n",
      "step 740/920 - loss: 0.0019 - 38ms/step\n",
      "step 750/920 - loss: 0.0019 - 38ms/step\n",
      "step 760/920 - loss: 7.8796e-04 - 38ms/step\n",
      "step 770/920 - loss: 4.4448e-04 - 38ms/step\n",
      "step 780/920 - loss: 9.3488e-04 - 38ms/step\n",
      "step 790/920 - loss: 7.9751e-04 - 38ms/step\n",
      "step 800/920 - loss: 0.0086 - 38ms/step\n",
      "step 810/920 - loss: 6.4766e-04 - 38ms/step\n",
      "step 820/920 - loss: 9.0606e-04 - 38ms/step\n",
      "step 830/920 - loss: 6.3177e-04 - 38ms/step\n",
      "step 840/920 - loss: 9.3900e-04 - 38ms/step\n",
      "step 850/920 - loss: 5.5549e-04 - 38ms/step\n",
      "step 860/920 - loss: 0.0024 - 38ms/step\n",
      "step 870/920 - loss: 0.0032 - 38ms/step\n",
      "step 880/920 - loss: 5.9416e-04 - 38ms/step\n",
      "step 890/920 - loss: 4.9174e-04 - 38ms/step\n",
      "step 900/920 - loss: 0.0019 - 38ms/step\n",
      "step 910/920 - loss: 0.0044 - 38ms/step\n",
      "step 920/920 - loss: 9.3785e-04 - 38ms/step\n",
      "Epoch 5/5\n",
      "step  10/920 - loss: 6.6190e-04 - 39ms/step\n",
      "step  20/920 - loss: 0.0013 - 37ms/step\n",
      "step  30/920 - loss: 0.0012 - 37ms/step\n",
      "step  40/920 - loss: 0.0010 - 37ms/step\n",
      "step  50/920 - loss: 5.2029e-04 - 37ms/step\n",
      "step  60/920 - loss: 0.0029 - 37ms/step\n",
      "step  70/920 - loss: 3.6647e-04 - 37ms/step\n",
      "step  80/920 - loss: 7.4757e-04 - 37ms/step\n",
      "step  90/920 - loss: 0.0041 - 37ms/step\n",
      "step 100/920 - loss: 0.0017 - 37ms/step\n",
      "step 110/920 - loss: 0.0030 - 37ms/step\n",
      "step 120/920 - loss: 5.7994e-04 - 37ms/step\n",
      "step 130/920 - loss: 7.7253e-04 - 37ms/step\n",
      "step 140/920 - loss: 0.0029 - 37ms/step\n",
      "step 150/920 - loss: 8.3211e-04 - 37ms/step\n",
      "step 160/920 - loss: 0.0012 - 37ms/step\n",
      "step 170/920 - loss: 0.0014 - 37ms/step\n",
      "step 180/920 - loss: 9.2094e-04 - 37ms/step\n",
      "step 190/920 - loss: 7.0976e-04 - 37ms/step\n",
      "step 200/920 - loss: 0.0017 - 37ms/step\n",
      "step 210/920 - loss: 0.0016 - 37ms/step\n",
      "step 220/920 - loss: 0.0014 - 37ms/step\n",
      "step 230/920 - loss: 0.0021 - 37ms/step\n",
      "step 240/920 - loss: 8.0932e-04 - 37ms/step\n",
      "step 250/920 - loss: 0.0016 - 37ms/step\n",
      "step 260/920 - loss: 0.0035 - 37ms/step\n",
      "step 270/920 - loss: 0.0013 - 37ms/step\n",
      "step 280/920 - loss: 9.4124e-04 - 37ms/step\n",
      "step 290/920 - loss: 0.0012 - 37ms/step\n",
      "step 300/920 - loss: 4.0167e-04 - 37ms/step\n",
      "step 310/920 - loss: 0.0018 - 37ms/step\n",
      "step 320/920 - loss: 9.6177e-04 - 37ms/step\n",
      "step 330/920 - loss: 0.0012 - 37ms/step\n",
      "step 340/920 - loss: 6.6086e-04 - 37ms/step\n",
      "step 350/920 - loss: 6.6167e-04 - 37ms/step\n",
      "step 360/920 - loss: 0.0019 - 37ms/step\n",
      "step 370/920 - loss: 0.0135 - 37ms/step\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step 380/920 - loss: 0.0035 - 37ms/step\n",
      "step 390/920 - loss: 0.0021 - 37ms/step\n",
      "step 400/920 - loss: 0.0017 - 37ms/step\n",
      "step 410/920 - loss: 0.0011 - 37ms/step\n",
      "step 420/920 - loss: 0.0023 - 37ms/step\n",
      "step 430/920 - loss: 4.7484e-04 - 37ms/step\n",
      "step 440/920 - loss: 0.0011 - 37ms/step\n",
      "step 450/920 - loss: 0.0012 - 37ms/step\n",
      "step 460/920 - loss: 0.0011 - 37ms/step\n",
      "step 470/920 - loss: 0.0018 - 37ms/step\n",
      "step 480/920 - loss: 0.0014 - 37ms/step\n",
      "step 490/920 - loss: 0.0014 - 37ms/step\n",
      "step 500/920 - loss: 0.0015 - 37ms/step\n",
      "step 510/920 - loss: 0.0020 - 37ms/step\n",
      "step 520/920 - loss: 0.0028 - 37ms/step\n",
      "step 530/920 - loss: 0.0021 - 37ms/step\n",
      "step 540/920 - loss: 0.0034 - 37ms/step\n",
      "step 550/920 - loss: 4.9844e-04 - 37ms/step\n",
      "step 560/920 - loss: 0.0012 - 37ms/step\n",
      "step 570/920 - loss: 0.0020 - 37ms/step\n",
      "step 580/920 - loss: 4.3098e-04 - 37ms/step\n",
      "step 590/920 - loss: 9.7838e-04 - 37ms/step\n",
      "step 600/920 - loss: 0.0035 - 37ms/step\n",
      "step 610/920 - loss: 0.0020 - 37ms/step\n",
      "step 620/920 - loss: 9.6964e-04 - 37ms/step\n",
      "step 630/920 - loss: 0.0013 - 37ms/step\n",
      "step 640/920 - loss: 2.7093e-04 - 37ms/step\n",
      "step 650/920 - loss: 5.8872e-04 - 37ms/step\n",
      "step 660/920 - loss: 0.0011 - 37ms/step\n",
      "step 670/920 - loss: 0.0030 - 37ms/step\n",
      "step 680/920 - loss: 0.0011 - 37ms/step\n",
      "step 690/920 - loss: 0.0018 - 37ms/step\n",
      "step 700/920 - loss: 5.7134e-04 - 37ms/step\n",
      "step 710/920 - loss: 0.0051 - 37ms/step\n",
      "step 720/920 - loss: 7.1116e-04 - 37ms/step\n",
      "step 730/920 - loss: 0.0016 - 37ms/step\n",
      "step 740/920 - loss: 6.7312e-04 - 37ms/step\n",
      "step 750/920 - loss: 6.6027e-04 - 37ms/step\n",
      "step 760/920 - loss: 0.0021 - 37ms/step\n",
      "step 770/920 - loss: 6.6772e-04 - 37ms/step\n",
      "step 780/920 - loss: 0.0021 - 37ms/step\n",
      "step 790/920 - loss: 3.8518e-04 - 37ms/step\n",
      "step 800/920 - loss: 0.0021 - 37ms/step\n",
      "step 810/920 - loss: 8.5114e-04 - 37ms/step\n",
      "step 820/920 - loss: 0.0015 - 37ms/step\n",
      "step 830/920 - loss: 0.0012 - 37ms/step\n",
      "step 840/920 - loss: 0.0031 - 37ms/step\n",
      "step 850/920 - loss: 0.0017 - 37ms/step\n",
      "step 860/920 - loss: 0.0032 - 37ms/step\n",
      "step 870/920 - loss: 0.0030 - 37ms/step\n",
      "step 880/920 - loss: 3.4778e-04 - 37ms/step\n",
      "step 890/920 - loss: 0.0019 - 37ms/step\n",
      "step 900/920 - loss: 0.0024 - 37ms/step\n",
      "step 910/920 - loss: 0.0013 - 37ms/step\n",
      "step 920/920 - loss: 0.0032 - 37ms/step\n"
     ]
    }
   ],
   "source": [
    "# 模型组网\n",
    "model = nn.Sequential(\n",
    "    MyLSTM(6, 32, direction='bidirect', dropout=0.5),\n",
    "    nn.Linear(64, 1))\n",
    "\n",
    "model = paddle.Model(model)\n",
    "# 定义优化器、损失函数\n",
    "model.prepare(paddle.optimizer.RMSProp(0.0001, parameters=model.parameters()),\n",
    "              paddle.nn.MSELoss())\n",
    "# 模型训练\n",
    "model.fit(MyDataset('train'), epochs=5,\n",
    "          batch_size=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1f1fc6d6",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:38:05.302063Z",
     "start_time": "2022-04-27T06:37:39.575521Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  0%|                                                  | 0/7354 [00:00<?, ?it/s]WARNING: Detect dataset only contains single fileds, return format changed since Paddle 2.1. In Paddle <= 2.0, DataLoader add a list surround output data(e.g. return [data]), and in Paddle >= 2.1, DataLoader return the single filed directly (e.g. return data). For example, in following code: \n",
      "\n",
      "import numpy as np\n",
      "from paddle.io import DataLoader, Dataset\n",
      "\n",
      "class RandomDataset(Dataset):\n",
      "    def __getitem__(self, idx):\n",
      "        data = np.random.random((2, 3)).astype('float32')\n",
      "\n",
      "        return data\n",
      "\n",
      "    def __len__(self):\n",
      "        return 10\n",
      "\n",
      "dataset = RandomDataset()\n",
      "loader = DataLoader(dataset, batch_size=1)\n",
      "data = next(loader())\n",
      "\n",
      "In Paddle <= 2.0, data is in format '[Tensor(shape=(1, 2, 3), dtype=float32)]', and in Paddle >= 2.1, data is in format 'Tensor(shape=(1, 2, 3), dtype=float32)'\n",
      "\n",
      "100%|██████████████████████████████████████| 7354/7354 [00:25<00:00, 285.97it/s]\n"
     ]
    }
   ],
   "source": [
    "# 模型预测\n",
    "# y_pred = model.predict(MyDataset('test'))\n",
    "last_pred = deque(maxlen=192)\n",
    "pred_value = []\n",
    "for i in tqdm(range(test_X_tensor.shape[0])):\n",
    "    sub_tensor = test_X_tensor[i]\n",
    "    if last_pred:\n",
    "        num = len(last_pred)\n",
    "        sub_array = sub_tensor.numpy()\n",
    "        sub_array[-num:][:,-1] = list(last_pred)\n",
    "        sub_tensor = paddle.to_tensor(sub_array)\n",
    "    res = model.predict(MyDataset('test', sub_tensor), verbose=0)[0][0][0][0]\n",
    "    pred_value.append(res)\n",
    "    last_pred.append(res)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "8e0d00e4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:38:10.534089Z",
     "start_time": "2022-04-27T06:38:10.493537Z"
    }
   },
   "outputs": [],
   "source": [
    "# 预测结果转为列表\n",
    "y_pred_list = pred_value\n",
    "# 还原成价格\n",
    "pred_price_unscaled = price_scaler.inverse_transform(np.array(y_pred_list).reshape(-1,1))\n",
    "# 价格的后处理\n",
    "pred_price = []\n",
    "for i in pred_price_unscaled:\n",
    "    if i[0] < 0:\n",
    "        pred_price.append(0)\n",
    "    elif i[0] > 1500:\n",
    "        pred_price.append(1500)\n",
    "    else:\n",
    "        pred_price.append(i[0])\n",
    "\n",
    "# 真实值\n",
    "true_price = [i[0] for i in price_scaler.inverse_transform(test_y.reshape(-1,1))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f8665b8d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:38:11.897820Z",
     "start_time": "2022-04-27T06:38:11.893630Z"
    }
   },
   "outputs": [],
   "source": [
    "fx_pred = all_df['统一出清价格-日前预测'][-test_size:].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "71f3b3ed",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:38:12.623104Z",
     "start_time": "2022-04-27T06:38:12.604055Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BiLSTM model's mape:  5.7664624012026495\n",
      "FX's mape          :  5.987340938467889\n"
     ]
    }
   ],
   "source": [
    "print('BiLSTM model\\'s mape: ', filtered_mape(true_price, pred_price))\n",
    "print('FX\\'s mape          : ', filtered_mape(true_price, fx_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "4ca63970",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:38:39.959779Z",
     "start_time": "2022-04-27T06:38:39.720075Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_curve(true_price, pred_price, test_timestamp, start_idx=15, interval=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "5116ec6c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:38:56.442581Z",
     "start_time": "2022-04-27T06:38:56.439451Z"
    }
   },
   "outputs": [],
   "source": [
    "train_rf = all_df.iloc[:train_size]\n",
    "test_rf = all_df.iloc[-test_size:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "b095808c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:40:26.575439Z",
     "start_time": "2022-04-27T06:38:58.835924Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RandomForestRegressor(criterion='absolute_error', n_estimators=10,\n",
       "                      random_state=123)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rf = RandomForestRegressor(n_estimators=10, criterion='absolute_error', random_state=123)\n",
    "rf.fit(train_rf[['省调负荷-日前(MW)', '新能源负荷-日前(MW)', 'is_peak', 'weekday', 'is_weekend']], train_rf['统一出清价格-日前(元/MWh)'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "9d5e8b68",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:41:22.288370Z",
     "start_time": "2022-04-27T06:41:22.259365Z"
    }
   },
   "outputs": [],
   "source": [
    "rf_pred = rf.predict(test_rf[['省调负荷-日前(MW)', '新能源负荷-日前(MW)', 'is_peak', 'weekday', 'is_weekend']])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "89cdd803",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:41:33.459553Z",
     "start_time": "2022-04-27T06:41:33.441692Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BiLSTM model's mape:  20.080068130311837\n"
     ]
    }
   ],
   "source": [
    "rf_pred_price = []\n",
    "for i in rf_pred:\n",
    "    if i < 0:\n",
    "        rf_pred_price.append(0)\n",
    "    elif i > 1500:\n",
    "        rf_pred_price.append(1500)\n",
    "    else:\n",
    "        rf_pred_price.append(i)\n",
    "print('BiLSTM model\\'s mape: ', filtered_mape(true_price, rf_pred_price))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "fa7f860a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:41:40.679632Z",
     "start_time": "2022-04-27T06:41:40.666957Z"
    }
   },
   "outputs": [],
   "source": [
    "avg_pred = []\n",
    "for i in range(len(rf_pred)):\n",
    "    avg_pred.append((rf_pred_price[i] + pred_price[i]) / 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "105a660a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-04-27T06:41:42.753473Z",
     "start_time": "2022-04-27T06:41:42.741919Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "BiLSTM model's mape:  12.8325413876782\n"
     ]
    }
   ],
   "source": [
    "print('BiLSTM model\\'s mape: ', filtered_mape(true_price, avg_pred))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.11"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
